package SocialMediaSentiment;

import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.StringTokenizer;

import jxl.write.WriteException;

public class kFoldPosNeg {

	public static void main(String[] args) throws IOException, WriteException {
		int kfold = 10;
		String tweetsFile = "CorrectedTweets.xls";
		HashMap<Integer, HashMap<String, String>[]> sets = new HashMap<Integer, HashMap<String, String>[]>();
		HashMap<Integer, HashMap<String, Float>[]> wordCounters = new HashMap<Integer, HashMap<String, Float>[]>();
		for (int i = 1; i <= kfold; i++) {
			HashMap<String, String>[] trainVilisetsK = createSets(tweetsFile,
					i, kfold);
			sets.put(i, trainVilisetsK);
			HashMap<String, Float>[] wordCountsK = createWordCounts(trainVilisetsK[0]);
			wordCounters.put(i, wordCountsK);
		}
		float[] sentimentchance = getSentimentChance(sets.get(1)[0]);
		HashMap<String, String>[] wrongs = naiveBayes(sets.get(1),  sentimentchance, wordCounters.get(1));
		HashMap<String, Float> updated = updateCounters(wrongs[0], wordCounters.get(1)[0]);
		wordCounters.get(1)[0] = updated;
		HashMap<String, String>[] wrongs2 = naiveBayes(sets.get(1),  sentimentchance, wordCounters.get(1));
	}

	public static HashMap<String, String>[] naiveBayes(
		HashMap<String, String>[] sets, float[] sentimentChance,
		HashMap<String, Float>[] wordsCounts) throws IOException {
		HashMap<String, Float> wordsCountNegatief = wordsCounts[0];
		HashMap<String, Float> wordsCountPositief = wordsCounts[1];
		HashMap<String, Float> wordsCountAll = wordsCounts[2];
		HashMap<String, String> trainSet = sets[0];
		HashMap<String, String> validationSet = sets[1];
		HashMap<String, String> wrongNegatief = new HashMap<String, String>();
		HashMap<String, String> wrongPositief = new HashMap<String, String>();
		HashMap<String, String> wrongNegatiefValidate = new HashMap<String, String>();
		HashMap<String, String> wrongPositiefValidate = new HashMap<String, String>();
		
		int totalNegatief = 0;
		int totalPositief = 0;
		int totalNegatiefWrong = 0;
		int totalPositiefWrong = 0;

		float sentimentChanceNegatief = sentimentChance[0];
		float sentimentChancePositief = sentimentChance[1];
		float totalWordsNegatief = getTotalCount(wordsCountNegatief);
		float totalWordsPositief = getTotalCount(wordsCountPositief);

		System.out.println(totalWordsNegatief + "  " + totalWordsPositief);

		Iterator<String> k = (Iterator<String>) trainSet.keySet().iterator();
		while (k.hasNext()) {
			String tweet = k.next();
			int sentiment = Integer.parseInt(trainSet.get(tweet).replace(" ",
					""));
			float posNegatief = getTweetPos(tweet, wordsCountNegatief, totalWordsNegatief,
					sentimentChanceNegatief, wordsCountAll);
			float posPositief = getTweetPos(tweet, wordsCountPositief,
					totalWordsPositief, sentimentChancePositief, wordsCountAll);
			// System.out.println(posNegatief + " " + posPositief);
			int classi = getClassification(posNegatief, posPositief);
			if (sentiment < 0) {
				if ((classi >= 0)) {
					wrongNegatief.put(tweet, "" + classi);
					totalNegatiefWrong++;
				}
				totalNegatief++;
			} else if(sentiment > 0){// sentiment != 0
				if (classi <= 0) {
					wrongPositief.put(tweet, "" + classi);
					totalPositiefWrong++;
				}
				totalPositief++;

			}

		}
		System.out
				.println("||||||||||||||||||TRAINSET||||||||||||||||||||||||");
		System.out.println("\t" + "Negative\t" + "Positive");
		System.out.println("total:\t" + totalNegatief + "\t\t" + totalPositief);
		System.out.println("wrong:\t" + totalNegatiefWrong + "\t\t"
				+ totalPositiefWrong);
		System.out.println("||||||||||||||||||||||||||||||||||||||||||||||||");

		// ///////////////////////TESTSETRUN/////////////////////////
		int totalNegatiefTest = 0;
		int totalPositiefTest = 0;
		int totalNegatiefWrongTest = 0;
		int totalPositiefWrongTest = 0;

		k = (Iterator<String>) validationSet.keySet().iterator();
		while (k.hasNext()) {
			String tweet = k.next();
			int sentiment = Integer.parseInt(validationSet.get(tweet).replace(
					" ", ""));
			float posNegatief = getTweetPos(tweet, wordsCountNegatief, totalWordsNegatief,
					sentimentChanceNegatief, wordsCountAll);
			float posPositief = getTweetPos(tweet, wordsCountPositief,
					totalWordsPositief, sentimentChancePositief, wordsCountAll);
			// System.out.println(posNegatief + " " + posPositief);
			int classi = getClassification(posNegatief, posPositief);
			if (sentiment < 0) {
				if (classi >= 0) {
					totalNegatiefWrongTest++;
					wrongNegatiefValidate.put(tweet,""+classi);
				}
				totalNegatiefTest++;
			} else if(sentiment>0){// sentiment != 0
				if (classi <= 0) {
					totalPositiefWrongTest++;
					wrongPositiefValidate.put(tweet,""+classi);
				}
				totalPositiefTest++;
			}

		}
		System.out
				.println("|||||||||||||||||||TESTSET||||||||||||||||||||||||");
		System.out.println("\t" + "Negative\t" + "Positive");
		System.out.println("total:\t" + totalNegatiefTest + "\t\t"
				+ totalPositiefTest);
		System.out.println("wrong:\t" + totalNegatiefWrongTest +" "+(int)(((double)totalNegatiefWrongTest/(double)totalNegatiefTest)*100)+ "%\t\t"
				+ totalPositiefWrongTest+ " "+(int)(((double)totalPositiefWrongTest/(double)totalPositiefTest)*100) +"%");
		System.out.println("||||||||||||||||||||||||||||||||||||||||||||||||");

		HashMap[] wrongs = new HashMap[2];
		wrongs[0] = wrongNegatief;
		wrongs[1] = wrongPositief;
		return wrongs;

	}

	public static HashMap<String, Float> updateCounters(
			HashMap<String, String> wrongTweetClassi,
			HashMap<String, Float> wordCount) {
		Iterator<String> k2 = (Iterator<String>) wrongTweetClassi.keySet()
				.iterator();
		while (k2.hasNext()) {
			String tweet = k2.next();
			StringTokenizer tokenizer = new StringTokenizer(tweet, " ");
			while (tokenizer.hasMoreTokens()) {
				String word = tokenizer.nextToken();
				Float value;
				if (wordCount.containsKey(word)) {
					value = wordCount.get(word) + 1;
				} else {
					value = (float) 1;
				}
				wordCount.put(word, value);
			}
		}
		return wordCount;
	}

	public static int getClassification(float Negatief, float Positief) {
		int classification = -1;
		if (Positief > Negatief)
			classification = 1;
		return classification;
	}

	public static float getTweetPos(String tweet,
			HashMap<String, Float> wordsCount, float totalWords,
			float sentimentChance, HashMap<String, Float> wordsCountAll) {
		StringTokenizer tokenizer = new StringTokenizer(tweet);
		Float chance;
		float tweetPos = sentimentChance;
		// float words = tokenizer.countTokens();
		// tweetPos = 0;
		while (tokenizer.hasMoreTokens()) {
			String word = tokenizer.nextToken();
			if (wordsCountAll.keySet().contains(word)) {
				try {
					chance = (2 * wordsCount.get(word)) / totalWords;
				} catch (NullPointerException e) {
					chance = 1 / totalWords;
				}

				// System.out.println(chance + "  " + tweetPos + "   " + word);
				tweetPos = tweetPos * chance * 1000;
			}
		}
		return tweetPos;
	}

	public static HashMap<String, Float> getWordsCount(String file)
			throws IOException {
		HashMap<String, Float> wordsCount = new HashMap<String, Float>();
		HashMap<Integer, String[]> IndexWordsCounter = ReadExcel.read(file, 0,
				1);
		Iterator<Integer> k = (Iterator<Integer>) IndexWordsCounter.keySet()
				.iterator();
		while (k.hasNext()) {
			int index = k.next();
			String[] WordsCounter = IndexWordsCounter.get(index);
			String word = WordsCounter[0];
			float count = Float.parseFloat(WordsCounter[1]);
			wordsCount.put(word, (count + 1));
		}
		return wordsCount;
	}

	public static float getTotalCount(HashMap<String, Float> wordsCount)
			throws IOException {
		float total = 0;
		Iterator<String> k = (Iterator<String>) wordsCount.keySet().iterator();
		total += wordsCount.keySet().size();
		while (k.hasNext()) {
			String word = k.next();
			float count = wordsCount.get(word);
			total += count;
		}
		return total;
	}

	public static float[] getSentimentChance(HashMap<String, String> tweets)
			throws IOException {
		float[] sentimentChance = new float[2];
		float Negatief = 0;
		float Positief = 0;
		float total = 0;

		Iterator<String> k = (Iterator<String>) tweets.keySet()
				.iterator();
		while (k.hasNext()) {
			String tweet = k.next();
			int TweetSentiment = Integer
					.parseInt(tweets.get(tweet).replace(" ", ""));;
			if (TweetSentiment > 0)
				Positief++;
			else if (TweetSentiment < 0)
				Negatief++;
			total++;
		}
		sentimentChance[0] = Negatief / total;
		sentimentChance[1] = Positief / total;
		return sentimentChance;

	}

	public static HashMap<String, String>[] createSets(String alltweetsFile,
			int times, int kfold) throws IOException {

		HashMap<Integer, String[]> tweetsWithSentiment = ReadExcel.read(
				alltweetsFile, 0, 1);
		int maxindex = tweetsWithSentiment.size() - 1;
		Iterator<Integer> k = (Iterator<Integer>) tweetsWithSentiment.keySet()
				.iterator();
		HashMap<String, String> trainSet = new HashMap<String, String>();
		HashMap<String, String> validationSet = new HashMap<String, String>();

		while (k.hasNext()) {
			int index = k.next();
			String[] tweetSentiment = tweetsWithSentiment.get(index);

			if (index < (maxindex - (maxindex / kfold * times))
					|| index > (maxindex - (maxindex / kfold * (times - 1)))) {
				trainSet.put(tweetSentiment[0], tweetSentiment[1]);
			} else {
				validationSet.put(tweetSentiment[0], tweetSentiment[1]);
			}
		}
		HashMap[] kfoldSets = new HashMap[2];
		kfoldSets[0] = trainSet;
		kfoldSets[1] = validationSet;

		return kfoldSets;
	}

	public static HashMap<String, Float>[] createWordCounts(
			HashMap<String, String> trainSet) {
		HashMap[] counters = new HashMap[3];
		HashMap<String, Float> wordsCountAll = new HashMap<String, Float>();
		HashMap<String, Float> wordsCountNegatief = new HashMap<String, Float>();
		HashMap<String, Float> wordsCountPositief = new HashMap<String, Float>();
		Iterator<String> k2 = (Iterator<String>) trainSet.keySet().iterator();
		while (k2.hasNext()) {
			String tweet = k2.next();
			int sentiment = Integer.parseInt(trainSet.get(tweet).replace(" ",
					""));
			StringTokenizer st = new StringTokenizer(tweet,
					" \r\n\t\f,.!$%^&*()[]{}-=\\;<>/?");
			if (sentiment < 0) {
				while (st.hasMoreTokens()) {
					String key = st.nextToken();
					float value;
					if (wordsCountNegatief.containsKey(key)) {
						value = wordsCountNegatief.get(key) + 1;
					} else {
						value = 1;
					}
					wordsCountNegatief.put(key, value);
					if (wordsCountAll.containsKey(key)) {
						value = wordsCountAll.get(key) + 1;
					} else {
						value = 1;
					}
					wordsCountAll.put(key, value);
				}
			} else if(sentiment > 0){
				while (st.hasMoreTokens()) {
					String key = st.nextToken();
					float value;
					if (wordsCountPositief.containsKey(key)) {
						value = wordsCountPositief.get(key) + 1;
					} else {
						value = 1;
					}
					wordsCountPositief.put(key, value);
					if (wordsCountAll.containsKey(key)) {
						value = wordsCountAll.get(key) + 1;
					} else {
						value = 1;
					}
					wordsCountAll.put(key, value);
				}
			}
		}
		counters[0] = wordsCountNegatief;
		counters[1] = wordsCountPositief;
		counters[2] = wordsCountAll;
		return counters;
	}

}
